


import re
import sys
import traceback
from redis import Redis
import json
from sqlalchemy.orm import Session
from app.common.enums import ErrTypes
from app.common.exceptions import GenericException
from app.common.regexps import variable_regexp, only_var_regexp

from app.core.rule_funcs import FUNCS_DICT

import logging
logger = logging.getLogger(__name__)

RISK_RULE_KEY = 'risk_rule'

'''
预留参数值:
${r}
${db}
${dyn}
'''

class RuleParser(object):

    gvars: dict = {}
    vars_dict = {}
    rules_dict = {}
    r: Redis
    rule_tpls: list = []
    rule_funcs: list = []
    result = True
    call_params: dict = {}

    #def __init__(self, db: Session, r: Redis, tpl: dict, call_params: dict={}):
    def __init__(self, r: Redis, tpl: dict, params: dict={}):
        logger.info('>> init RuleParser')
        self.r = r
        self.rule_funcs: list[dict] = tpl.get('funcs')
        self.gvars = {
            #'db': db,
            'r': r
        }
        self.vars_dict = dict(self.vars_dict, **self.gvars)
        self.call_params = params

    def parse(self):
        logger.info('------------ 解析规则 -------------')
        result = True
        for it in self.rule_funcs:
            logger.info(f'--> 解析数据项: {it}')
            try:
                fname = it.get('name')
                params = it.get('params')
                func = FUNCS_DICT.get(fname)
                if not func:
                    logger.error('规则函数名未配置')
                    raise GenericException(ErrTypes.rule_no_func_name)
                else:
                    if isinstance(params, dict):
                        for k in params:
                            if isinstance(params[k], str):
                                res = re.findall(only_var_regexp, params[k])
                                if res:
                                    logger.info(f'参数值为变量: {res[0]}')
                                    params[k] = self.vars_dict.get(res[0])
                        logger.info(f'函数[{fname}] 模板参数: {params}')
                    # exec func
                    #params = dict(self.payload_params, **tpl_params)
                    params['call_params'] = self.call_params
                    logger.info(f'函数[{fname}] 完整参数: {params}')
                    result = func(**params)
                    if not result:
                        logger.warning('解析结果不通过')
                        break
            except GenericException as err:
                logger.error(err.message)
                raise GenericException(err.error_type, message=err.message, data=err.data)
            except Exception as err:
                logger.error(f'解析函数[{it.get("name")}]错误')
                exc_type, exc_value, exc_obj = sys.exc_info()
                traceback.print_exception(exc_type,exc_value,exc_obj,limit=3,file=sys.stdout)
                raise GenericException(ErrTypes.rule_parse_error)
        logger.info('------------ 解析结束 -------------')
        return result

        